package com.blog.cmrpersonalblog.service.impl;

import com.blog.cmrpersonalblog.dto.markdown.requset.MarkdownPreviewRequest;
import com.blog.cmrpersonalblog.dto.markdown.respnose.MarkdownPreviewResponse;
import com.blog.cmrpersonalblog.service.MarkdownService;
import com.vladsch.flexmark.ext.autolink.AutolinkExtension;
import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension;
import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.data.MutableDataSet;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Markdown服务实现类
 */
@Slf4j
@Service
public class MarkdownServiceImpl implements MarkdownService {

    private final Parser parser;
    private final HtmlRenderer renderer;

    public MarkdownServiceImpl() {
        // 配置Markdown解析器选项
        MutableDataSet options = new MutableDataSet();
        
        // 启用扩展
        options.set(Parser.EXTENSIONS, Arrays.asList(
                TablesExtension.create(),
                TaskListExtension.create(),
                StrikethroughExtension.create(),
                AutolinkExtension.create()
        ));

        // 配置表格
        options.set(TablesExtension.COLUMN_SPANS, false)
                .set(TablesExtension.APPEND_MISSING_COLUMNS, true)
                .set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
                .set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true);

        // 配置任务列表
        options.set(TaskListExtension.ITEM_DONE_MARKER, "<input type=\"checkbox\" checked disabled>")
                .set(TaskListExtension.ITEM_NOT_DONE_MARKER, "<input type=\"checkbox\" disabled>");

        this.parser = Parser.builder(options).build();
        this.renderer = HtmlRenderer.builder(options).build();
    }

    @Override
    public String convertToHtml(String markdownContent) {
        if (markdownContent == null || markdownContent.trim().isEmpty()) {
            return "";
        }

        try {
            Node document = parser.parse(markdownContent);
            return renderer.render(document);
        } catch (Exception e) {
            log.error("Markdown转HTML失败", e);
            return "<p>内容解析失败</p>";
        }
    }

    @Override
    public MarkdownPreviewResponse preview(MarkdownPreviewRequest request) {
        long startTime = System.currentTimeMillis();
        
        try {
            String htmlContent = convertToHtml(request.getContent());
            MarkdownPreviewResponse response = new MarkdownPreviewResponse(request.getContent(), htmlContent);
            
            // 提取目录
            response.setTableOfContents(extractTableOfContents(request.getContent()));
            
            // 计算处理时间
            response.setProcessTime(System.currentTimeMillis() - startTime);
            
            return response;
        } catch (Exception e) {
            log.error("Markdown预览失败", e);
            MarkdownPreviewResponse response = new MarkdownPreviewResponse();
            response.setMarkdownContent(request.getContent());
            response.setHtmlContent("<p>预览失败：" + e.getMessage() + "</p>");
            response.setWordCount(0);
            response.setReadingTime(1);
            response.setProcessTime(System.currentTimeMillis() - startTime);
            return response;
        }
    }

    @Override
    public String extractTableOfContents(String markdownContent) {
        if (markdownContent == null || markdownContent.trim().isEmpty()) {
            return "[]";
        }

        StringBuilder toc = new StringBuilder();
        toc.append("[");
        
        Pattern headingPattern = Pattern.compile("^(#{1,6})\\s+(.+)$", Pattern.MULTILINE);
        Matcher matcher = headingPattern.matcher(markdownContent);
        
        boolean first = true;
        while (matcher.find()) {
            if (!first) {
                toc.append(",");
            }
            
            int level = matcher.group(1).length();
            String title = matcher.group(2).trim();
            String anchor = generateAnchor(title);
            
            toc.append("{")
               .append("\"level\":").append(level).append(",")
               .append("\"title\":\"").append(escapeJson(title)).append("\",")
               .append("\"anchor\":\"").append(anchor).append("\"")
               .append("}");
            
            first = false;
        }
        
        toc.append("]");
        return toc.toString();
    }

    @Override
    public Integer calculateWordCount(String markdownContent) {
        if (markdownContent == null || markdownContent.trim().isEmpty()) {
            return 0;
        }
        
        // 移除Markdown标记符号
        String cleanContent = markdownContent
                .replaceAll("#+\\s*", "") // 移除标题标记
                .replaceAll("\\*\\*([^*]+)\\*\\*", "$1") // 移除粗体标记
                .replaceAll("\\*([^*]+)\\*", "$1") // 移除斜体标记
                .replaceAll("`([^`]+)`", "$1") // 移除行内代码标记
                .replaceAll("```[\\s\\S]*?```", "") // 移除代码块
                .replaceAll("!\\[([^\\]]*)\\]\\([^)]*\\)", "$1") // 移除图片标记
                .replaceAll("\\[([^\\]]*)\\]\\([^)]*\\)", "$1") // 移除链接标记
                .replaceAll("\\n", " ") // 换行符替换为空格
                .trim();
        
        // 中文字符按1个字计算，英文单词按空格分割计算
        int chineseCount = 0;
        int englishCount = 0;
        
        for (char c : cleanContent.toCharArray()) {
            if (c >= 0x4e00 && c <= 0x9fff) {
                chineseCount++;
            }
        }
        
        String[] englishWords = cleanContent.replaceAll("[\\u4e00-\\u9fff]", "").split("\\s+");
        for (String word : englishWords) {
            if (!word.trim().isEmpty()) {
                englishCount++;
            }
        }
        
        return chineseCount + englishCount;
    }

    @Override
    public Integer calculateReadingTime(Integer wordCount) {
        if (wordCount == null || wordCount == 0) {
            return 1;
        }
        // 按每分钟200字计算
        int minutes = (int) Math.ceil(wordCount / 200.0);
        return Math.max(1, minutes); // 最少1分钟
    }

    @Override
    public String stripHtmlTags(String htmlContent) {
        if (htmlContent == null || htmlContent.trim().isEmpty()) {
            return "";
        }
        return htmlContent.replaceAll("<[^>]+>", "").trim();
    }

    @Override
    public String generateSummary(String markdownContent, Integer maxLength) {
        if (markdownContent == null || markdownContent.trim().isEmpty()) {
            return "";
        }
        
        if (maxLength == null || maxLength <= 0) {
            maxLength = 200;
        }
        
        // 转换为HTML后去除标签
        String htmlContent = convertToHtml(markdownContent);
        String plainText = stripHtmlTags(htmlContent);
        
        if (plainText.length() <= maxLength) {
            return plainText;
        }
        
        // 截取指定长度，并在最后一个完整词处截断
        String summary = plainText.substring(0, maxLength);
        int lastSpace = summary.lastIndexOf(' ');
        if (lastSpace > maxLength * 0.8) { // 如果最后一个空格位置合理
            summary = summary.substring(0, lastSpace);
        }
        
        return summary + "...";
    }

    /**
     * 生成锚点链接
     */
    private String generateAnchor(String title) {
        return title.toLowerCase()
                .replaceAll("[^a-zA-Z0-9\\u4e00-\\u9fff\\s-]", "")
                .replaceAll("\\s+", "-")
                .replaceAll("-+", "-")
                .replaceAll("^-|-$", "");
    }

    /**
     * 转义JSON字符串
     */
    private String escapeJson(String str) {
        return str.replace("\\", "\\\\")
                .replace("\"", "\\\"")
                .replace("\n", "\\n")
                .replace("\r", "\\r")
                .replace("\t", "\\t");
    }
}
